/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using UnitedBinary.Core.Windows.Forms;
using UnitedBinary.HarnessIt.Controls;
using UnitedBinary.HarnessIt.SharedTypes;
using UnitedBinary.HarnessIt.TestEngine;
using UnitedBinary.UnitTests.Framework;
using UnitedBinary.UnitTests.Framework.TestItems;
using Timer=System.Windows.Forms.Timer;

namespace UnitedBinary.HarnessIt
{
	internal class RunningTestsForm : Form
	{
		#region Member Variables

		private ITestEngine iTestEngine = null;
		private ArrayList Assemblies;
		private DateTime start;
		private DateTime end;
		private ProgressBar progressBarTest;
		private bool once = false;
		private Thread utThread;

		private Font font8 = new Font( "Tahoma", 8 );
		private Font font8B = new Font( "Tahoma", 8, FontStyle.Bold );
		private Font font8U = new Font( "Tahoma", 8, FontStyle.Underline );
		//	private SynchronizationContext syncCtx;

		/// <summary>
		///		RichTextComposition to render the "output log" while running tests.
		/// </summary>
		internal RichTextComposition rtComp = new RichTextComposition();

		private Button buttonCancel;
		private Timer timerBackgroundUiAction;
		private Queue<SendOrPostCallback> uiActionQueue = new Queue<SendOrPostCallback>();

		private IContainer components;
		private GroupBox groupBox1;
		private Label labelExeCount;
		private Label labelPassedCount;
		private Label labelFailedCount;
		private Label labelExe;
		private Label labelPass;
		private Label labelFail;
		private GroupBox groupBox2;
		private Label Label1;
		private Label label2;
		private Label label3;
		private Label labelAssembly;
		private Label labelMethod;
		private Label labelClass;
		private Label label4;
		private Label label5;
		private Label labelEngineName;
		private Label labelEngineStatus;

		public bool cancelled = false;

		private Assembly activeAssembly = null;
		private Class activeClass = null;
		private GroupBox groupBox3;
		private Method activeMethod = null;
		private string engineStatus = "";
		private string engineName = "";
		private Timer timerFormUiUpdate;

		private HarnessItTraceListener harnessitListener;

		#endregion

		#region Construction and Intialization

		/// <summary>
		///		Initializing constructor.
		/// </summary>
		/// <param name="ar">An array list of Assembly objects to run tests on.</param>
		internal RunningTestsForm(ArrayList ar, HarnessItTraceListener listener)
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// Add any constructor code after InitializeComponent call
			//
			Assemblies = ar;
			harnessitListener = listener;

			labelExeCount.Text = "0";
			labelPassedCount.Text = "0";
			labelFailedCount.Text = "0";

			//		syncCtx = SynchronizationContext.Current;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if ( disposing )
			{
				if ( components != null )
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#endregion

		#region Test Execution Code

		private string InitializeExecutionEngine()
		{
			engineStatus = "Initializing unit test execution engine ... ";
			SetActiveText( false );

			if ( TestExecutionEngine == null )
			{
				throw new Exception( "The test execution engine has not be set.  There is no engine to execute tests." );
			}

			engineName = TestExecutionEngine.Name;
			SetActiveText( false );

			return TestExecutionEngine.Initialize();
		}

		private string ShutdownExecutionEngine()
		{
			while ( uiActionQueue.Count > 0 && SystemInformation.UserInteractive )
			{
				engineStatus = "Finalizing test report...";
				SetActiveText( false );
				Thread.Sleep( 200 );
			}

			engineStatus = "Shutting down unit test execution engine ... ";
			SetActiveText( false );

			string msg = "";
			try
			{
				msg = TestExecutionEngine.Shutdown();
			}
			catch ( Exception e )
			{
				string err = "Error shutting down execution engine.\nSee output view for details.";

				if ( SystemInformation.UserInteractive )
				{
					MessageBox.Show( err, "Execution Engine Error", MessageBoxButtons.OK, MessageBoxIcon.Error );
				}
				else
				{
					EmergencyLog.WriteLine( "Error in execution engine.", err );
				}

				msg = "Error shutting down execution engine.\n\nDetails:\n" + e;
			}
			return msg;
		}

		// Variables for real-time result tracking.
		int passCount = 0;
		int failCount = 0;
		int exeCount = 0;

		/// <summary>
		///		Unit test execution thread entry point.  Run the unit tests for every
		///		active method then exits.
		/// </summary>
		internal void RunTests()
		{
			AddUIAction( delegate
			             	{
			             		progressBarTest.Maximum = TotalActiveTestCount;
			             		progressBarTest.Minimum = 0;
			             	} );

			AddUIAction( delegate
			             	{
			             		rtComp.Clear();
			             		rtComp.Font = font8;
			             	} );

			int count = TotalActiveTestCount;
			if ( count == 0 )
			{
				return;
			}

			foreach ( Assembly A in Assemblies )
			{
				A.ResetTests();
			}

			try
			{
				if ( TestExecutionEngine != null )
				{
					AddUIAction( delegate
					             	{
					             		RichTextString msg = new RichTextString();
					             		msg.Font = font8B;
					             		msg.Text = "Initializing test engine " + TestExecutionEngine.GetType().FullName;
					             		rtComp.AddLine( msg );
					             		rtComp.Render();
					             	} );
				}

				string engineMessage = InitializeExecutionEngine();
				AddUIAction( delegate
				             	{
				             		rtComp.AddLine( new RichTextString( engineMessage, font8 ) );
				             		rtComp.Render();
				             		rtComp.Render();
				             	} );
			}
			catch ( Exception e )
			{
				string msg = "Error initializing execution engine.\nSee output view for details.";
				if ( SystemInformation.UserInteractive )
				{
					MessageBox.Show( msg, "HarnessIt", MessageBoxButtons.OK, MessageBoxIcon.Error );
				}
				else
				{
					EmergencyLog.WriteLine( "Error initializing engine.", msg );
				}

				AddUIAction( delegate
				             	{
				             		string err = "Error initializing execution engine.\n\nException Message:\n" + e.Message;

				             		rtComp.AddLine( new RichTextString( err, font8 ) );
				             		rtComp.Render();
				             	} );
				return;
			}

			engineStatus = "Running tests";
			AddUIAction( delegate
			             	{
			             		harnessitListener.Clear();
			             		harnessitListener.WriteComment( "Starting tests..." );
			             		harnessitListener.WriteComment( "" );
			             	} );

			SetActiveText( false );

			int progress = 0;
			foreach ( Assembly A in Assemblies )
			{
				if ( A.ContainsActiveTests || A.ContainsRequiredTests )
				{
					activeAssembly = A;
					//UpdateForm( exeCount, passCount, failCount );

					Class c;
					Class[] classes = A.Classes;
					int cLength = classes.Length;

					for ( int k = 0; k < cLength; k++ )
					{
						c = classes[k];

						if ( c.ContainsActiveTests || c.ContainsRequiredTests )
						{
							activeClass = c;
							//UpdateForm( exeCount, passCount, failCount );

							AddProcessingClassText( c.Name );
							Method m;
							Method[] methods = c.Methods;
							int mLength = methods.Length;

							for ( int j = 0; j < mLength; j++ )
							{
								m = methods[j];
								if ( m.Active || m.TestRequired )
								{
									activeMethod = m;
									//UpdateForm( exeCount, passCount, failCount );
									AddUIAction( delegate
									             	{
									             		progress++;
									             		progressBarTest.Increment( 1 );
									             	} );

									AddExecutingTestStatement( c.Name, m.Name );

									TestMethodRecord tmr;
									try
									{
										TestExecutionEngine.RunTest( m );
									}
									catch ( Exception e )
									{
										tmr = new TestMethodRecord();

										StringBuilder sb = new StringBuilder();
										sb.Append( "Test Engine Exception: The test engine failed execute the test.\n\nDetails:\n" );
										sb.Append( e.ToString() );

										tmr.RunTest( false, sb.ToString() );

										m.TestRecord = tmr;
									}

									int testRecordCount = 0;
									tmr = m.TestRecord;
									int tCount = tmr.TestObjectCount;

									for ( int i = 0; i < tCount; i++ )
									{
										StringBuilder sb = new StringBuilder( 256 );

										TestObject o = m.TestRecord.GetResult( i );
										if ( o.TestObjectType == TestObjectTypes.TestResult )
										{
											TestResult tr = (TestResult)o;
											exeCount++;
											testRecordCount++;

											if ( tr.Success )
											{
												sb.Append( "Passed " );
												passCount++;
											}
											else
											{
												sb.Append( "FAILED " );
												failCount++;
											}
											sb.Append( "test " );
											sb.Append( testRecordCount.ToString() );
											sb.Append( ": " );
											sb.Append( tr.Description );

											AddTestResultText( passCount, failCount, exeCount, sb.ToString() );
										}
										else if ( o.TestObjectType == TestObjectTypes.TestComment )
										{
											TestComment tc = (TestComment)o;
											AddCommentText( tc.Comment );
										}
										else
										{
											AddUIAction(
												delegate { rtComp.AddLine( new RichTextString( "WARNING: Unknown Test Object Type.", Color.Red ) ); } );
										}
									}

									AddEndOfMethodText( m.RunningTime );
									TestStatusControl.AddTestResult(m);

									if ( cancelled )
									{
										AddCancelingAction();
										ShutdownExecutionEngine( rtComp );

										return;
									}
								}
							}
							AddEndOfTestSummary( c.Name, c.TestRecord.Failures );
						}
					}
				}
			}

			AddUISummary( passCount, failCount, exeCount );

			ShutdownExecutionEngine( rtComp );
			Debug.WriteLine( "HarnessIt unit testing thread exiting..." );
		}

		private void AddUISummary(int passCount, int failCount, int exeCount)
		{
			AddUIAction( delegate
         	{
         		string overview = "Summary: " + exeCount + " tests executed, " + passCount + " passed, and " +
         		                  failCount + " failed.";
         		rtComp.AddLine( new RichTextString( overview, Color.Black, font8 ) );
         		rtComp.AddLine( "" );
         		rtComp.Render();

         		harnessitListener.WriteComment( "" );
         		harnessitListener.WriteComment( "Tests complete." );
         		harnessitListener.ClearTestMemory();
         	} );
		}

		private void AddEndOfTestSummary(string cName1, int failures)
		{
			AddUIAction( delegate
     		{
     			RichTextString s2 = new RichTextString();
     			s2.Font = font8B;
     			if ( failures == 0 )
     			{
     				s2.Text = "All tests in " + cName1 + " succeeded.";
     				s2.B = 255;
     			}
     			else
     			{
     				s2.Text = "Failures occured in " + cName1 + ".";
     				s2.R = 255;
     			}

     			rtComp.AddLine( s2 );
     			rtComp.AddLine( "" );
     		} );
		}

		private void AddCancelingAction()
		{
			AddUIAction( delegate
         	{
         		string text = "CANCELLED REMAINING TESTS PER USER REQUEST.";
         		rtComp.AddLine( "" );
         		rtComp.AddLine( new RichTextString( text, Color.Red, font8B ) );
         		rtComp.AddLine( "" );
         		rtComp.Render();
         	} );
		}

		private void AddProcessingClassText(string cName)
		{
			AddUIAction( delegate { rtComp.AddLine( new RichTextString( "Processing class " + cName, font8B ) ); } );
		}

		private void AddTestResultText(int passCount, int failCount, int exeCount, string uiText)
		{
			AddUIAction( delegate
			             	{
			             		rtComp.AddLine( new RichTextString( uiText, font8 ) );
			             		//UpdateForm( exeCount, passCount, failCount );
			             	} );
		}

		private void AddExecutingTestStatement(string cName, string mName)
		{
			AddUIAction( delegate
			             	{
			             		StringBuilder textSB = new StringBuilder();
			             		textSB.Append( "Executing test method " );
			             		textSB.Append( cName );
			             		textSB.Append( "." );
			             		textSB.Append( mName );
			             		textSB.Append( "()" );

			             		rtComp.AddLine( new RichTextString( textSB.ToString(), font8U ) );
			             		rtComp.Render();

			             		harnessitListener.ActiveTest = cName + "." + mName;
			             	} );
		}

		private void AddEndOfMethodText(double mRunningTime)
		{
			AddUIAction( delegate
			             	{
			             		StringBuilder sb = new StringBuilder();
			             		sb.Append( "Method execution time: " );
			             		sb.Append( mRunningTime.ToString( "F3" ) );
			             		sb.Append( " seconds." );

			             		rtComp.AddLine( new RichTextString( sb.ToString(), Color.DarkGray, rtComp.Font ) );
			             		rtComp.Render();
			             	} );
		}

		private void AddCommentText(string tcComment)
		{
			AddUIAction( delegate
			             	{
			             		StringBuilder sb2 = new StringBuilder();
			             		sb2.Append( "Comment: " );
			             		sb2.Append( tcComment );

			             		rtComp.AddLine( new RichTextString( sb2.ToString(), Color.Green, rtComp.Font ) );
			             	} );
		}

		private void AddUIAction(SendOrPostCallback action)
		{
			lock ( uiActionQueue )
			{
				uiActionQueue.Enqueue( action );
			}
		}

		private void ShutdownExecutionEngine(RichTextComposition rtc)
		{
			RichTextString s = new RichTextString();
			try
			{
				if ( TestExecutionEngine != null )
				{
					AddUIAction( delegate
					             	{
					             		RichTextString msg = new RichTextString();
					             		msg.Font = font8B;
					             		msg.Text = "Shutting down test engine " + TestExecutionEngine.GetType().FullName;
					             		rtc.AddLine( msg );
					             		rtc.Render();
					             	} );
				}

				string txt = ShutdownExecutionEngine();
				AddUIAction( delegate
				             	{
				             		s.Font = font8;
				             		s.Text = txt;
				             		rtc.AddLine( s );
				             		rtc.Render();
				             	} );
			}
			catch ( Exception e )
			{
				string msg = "Error shutting down execution engine.\nSee output view for details.";
				if ( SystemInformation.UserInteractive )
				{
					MessageBox.Show( msg, "HarnessIt", MessageBoxButtons.OK, MessageBoxIcon.Error );
				}
				else
				{
					EmergencyLog.WriteLine( "Error stopping engine.", msg );
				}

				string err = "Error shutting down execution engine.\n\nDetails:\n" + e;

				AddUIAction( delegate
				             	{
				             		s = new RichTextString();
				             		s.Font = font8;
				             		s.Text = err;

				             		rtc.AddLine( s );
				             		rtc.Render();
				             	} );
			}
		}

		/// <summary>
		///		TotalActiveTestCount computes the number of active tests in the project.
		/// </summary>
		internal int TotalActiveTestCount
		{
			get
			{
				int i = 0;
				foreach ( Assembly A in Assemblies )
				{
					if ( A.ContainsActiveTests || A.ContainsRequiredTests )
					{
						Class[] classes = A.Classes;
						foreach ( Class c in classes )
						{
							if ( c.ContainsActiveTests || c.ContainsRequiredTests )
							{
								foreach ( Method m in c.Methods )
								{
									if ( m.Active || m.TestRequired )
									{
										i++;
									}
								}
							}
						}
					}
				}
				return i;
			}
		}

		/// <summary>
		///		Time when the tests started.
		/// </summary>
		internal DateTime Start
		{
			get { return start; }
		}

		/// <summary>
		///		Time when the tests completed.
		/// </summary>
		internal DateTime End
		{
			get { return end; }
		}

		/// <summary>
		///		Running time of the tests.
		/// </summary>
		internal TimeSpan Elapsed
		{
			get { return End - Start; }
		}

		private void UpdateForm()//int total, int pass, int fail)
		{
			if ( labelExeCount == null )
			{
				return;
			}

			try
			{
				InternalUpdateUi( passCount + failCount, passCount, failCount, true );
			}
			catch
			{
			}
		}

		private void InternalUpdateUi(int total, int pass, int fail, bool executeDirectly)
		{
			SendOrPostCallback callback = delegate
			{
				if ( fail > 0 )
				{
					labelExeCount.ForeColor = Color.Red;
					labelPassedCount.ForeColor = Color.Red;
					labelFailedCount.ForeColor = Color.Red;

					labelPass.ForeColor = Color.Red;
					labelFail.ForeColor = Color.Red;
					labelExe.ForeColor = Color.Red;
				}

				labelExeCount.Text = total.ToString();
				labelPassedCount.Text = pass.ToString();
				labelFailedCount.Text = fail.ToString();

				SetActiveText( executeDirectly );
				if ( activeAssembly != null && activeAssembly.TestRecord.Failures > 0 )
				{
					labelAssembly.ForeColor = Color.Red;
				}
				else
				{
					labelAssembly.ForeColor = Color.Blue;
				}

				if ( activeClass != null && activeClass.TestRecord.Failures > 0 )
				{
					labelClass.ForeColor = Color.Red;
				}
				else
				{
					labelClass.ForeColor = Color.Blue;
				}

				if ( activeMethod != null && activeMethod.TestRecord.Failures > 0 )
				{
					labelMethod.ForeColor = Color.Red;
				}
				else
				{
					labelMethod.ForeColor = Color.Blue;
				}
			};

			if (executeDirectly)
			{
				callback( null );
			}
			else
			{
				AddUIAction( callback );
			}
		}

		private void SetActiveText(bool executeDirectly)
		{
			SendOrPostCallback callback = delegate
          	{
          		if ( activeAssembly != null )
          		{
          			labelAssembly.Text =
          				TruncateText( labelAssembly.Width, activeAssembly.FullPathName );
          		}
          		if ( activeClass != null )
          		{
          			labelClass.Text = TruncateText( labelClass.Width, activeClass.FullName );
          		}
          		if ( activeMethod != null )
          		{
          			labelMethod.Text = TruncateText( labelMethod.Width, activeMethod.Name );
          		}

          		labelEngineStatus.Text = TruncateText( labelEngineStatus.Width, engineStatus );
          		labelEngineName.Text = TruncateText( labelEngineName.Width, engineName );
          	};

			if ( executeDirectly )
			{
				callback( null );
			}
			else
			{
				AddUIAction( callback );
			}
		}

		private string TruncateText(int pixels, string text)
		{
			if ( pixels < 12 )
			{
				return text;
			}

			Graphics g = labelAssembly.CreateGraphics();
			SizeF size = g.MeasureString( text, labelAssembly.Font );
			if ( size.Width < pixels )
			{
				return text;
			}

			while ( size.Width > pixels )
			{
				text = text.Remove( 0, 1 );
				size = g.MeasureString( "..." + text, labelAssembly.Font );
			}

			return "..." + text;
		}

		public ITestEngine TestExecutionEngine
		{
			get
			{
				if ( iTestEngine == null )
				{
					Debug.WriteLine( "HarnessIt: TestExecutionEngine has not been initialized. Test execution will fail." );
					throw new ArgumentNullException( "TestExecutionEngine", "TestExecutionEngine has not be initialized." );
				}

				return iTestEngine;
			}
			set { iTestEngine = value; }
		}

		public TestStatusControl TestStatusControl { get; set; }

		#endregion

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager( typeof( RunningTestsForm ) );
			this.progressBarTest = new System.Windows.Forms.ProgressBar();
			this.buttonCancel = new System.Windows.Forms.Button();
			this.timerBackgroundUiAction = new System.Windows.Forms.Timer( this.components );
			this.groupBox1 = new System.Windows.Forms.GroupBox();
			this.labelFailedCount = new System.Windows.Forms.Label();
			this.labelPassedCount = new System.Windows.Forms.Label();
			this.labelExeCount = new System.Windows.Forms.Label();
			this.labelFail = new System.Windows.Forms.Label();
			this.labelPass = new System.Windows.Forms.Label();
			this.labelExe = new System.Windows.Forms.Label();
			this.groupBox2 = new System.Windows.Forms.GroupBox();
			this.labelClass = new System.Windows.Forms.Label();
			this.labelMethod = new System.Windows.Forms.Label();
			this.labelAssembly = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.Label1 = new System.Windows.Forms.Label();
			this.groupBox3 = new System.Windows.Forms.GroupBox();
			this.labelEngineStatus = new System.Windows.Forms.Label();
			this.labelEngineName = new System.Windows.Forms.Label();
			this.label5 = new System.Windows.Forms.Label();
			this.label4 = new System.Windows.Forms.Label();
			this.timerFormUiUpdate = new System.Windows.Forms.Timer( this.components );
			this.groupBox1.SuspendLayout();
			this.groupBox2.SuspendLayout();
			this.groupBox3.SuspendLayout();
			this.SuspendLayout();
			// 
			// progressBarTest
			// 
			this.progressBarTest.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.progressBarTest.Location = new System.Drawing.Point( 14, 242 );
			this.progressBarTest.Name = "progressBarTest";
			this.progressBarTest.Size = new System.Drawing.Size( 500, 20 );
			this.progressBarTest.Step = 1;
			this.progressBarTest.TabIndex = 1;
			// 
			// buttonCancel
			// 
			this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
			this.buttonCancel.BackColor = System.Drawing.Color.White;
			this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.buttonCancel.Location = new System.Drawing.Point( 14, 270 );
			this.buttonCancel.Name = "buttonCancel";
			this.buttonCancel.Size = new System.Drawing.Size( 75, 23 );
			this.buttonCancel.TabIndex = 2;
			this.buttonCancel.Text = "STOP";
			this.buttonCancel.UseVisualStyleBackColor = false;
			this.buttonCancel.Click += new System.EventHandler( this.buttonCancel_Click );
			// 
			// timerBackgroundUiAction
			// 
			this.timerBackgroundUiAction.Tick += new System.EventHandler( this.OnTimer1Tick );
			// 
			// groupBox1
			// 
			this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.groupBox1.Controls.Add( this.labelFailedCount );
			this.groupBox1.Controls.Add( this.labelPassedCount );
			this.groupBox1.Controls.Add( this.labelExeCount );
			this.groupBox1.Controls.Add( this.labelFail );
			this.groupBox1.Controls.Add( this.labelPass );
			this.groupBox1.Controls.Add( this.labelExe );
			this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.groupBox1.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.groupBox1.ForeColor = System.Drawing.SystemColors.ControlText;
			this.groupBox1.Location = new System.Drawing.Point( 14, 8 );
			this.groupBox1.Name = "groupBox1";
			this.groupBox1.Size = new System.Drawing.Size( 500, 76 );
			this.groupBox1.TabIndex = 3;
			this.groupBox1.TabStop = false;
			this.groupBox1.Text = "Current Test Results";
			// 
			// labelFailedCount
			// 
			this.labelFailedCount.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelFailedCount.ForeColor = System.Drawing.Color.Blue;
			this.labelFailedCount.Location = new System.Drawing.Point( 104, 52 );
			this.labelFailedCount.Name = "labelFailedCount";
			this.labelFailedCount.Size = new System.Drawing.Size( 144, 16 );
			this.labelFailedCount.TabIndex = 5;
			this.labelFailedCount.Text = "FAIL_COUNT";
			// 
			// labelPassedCount
			// 
			this.labelPassedCount.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelPassedCount.ForeColor = System.Drawing.Color.Blue;
			this.labelPassedCount.Location = new System.Drawing.Point( 104, 36 );
			this.labelPassedCount.Name = "labelPassedCount";
			this.labelPassedCount.Size = new System.Drawing.Size( 144, 16 );
			this.labelPassedCount.TabIndex = 4;
			this.labelPassedCount.Text = "PASS_COUNT";
			// 
			// labelExeCount
			// 
			this.labelExeCount.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelExeCount.ForeColor = System.Drawing.Color.Blue;
			this.labelExeCount.Location = new System.Drawing.Point( 104, 20 );
			this.labelExeCount.Name = "labelExeCount";
			this.labelExeCount.Size = new System.Drawing.Size( 144, 16 );
			this.labelExeCount.TabIndex = 3;
			this.labelExeCount.Text = "EXE_COUNT";
			// 
			// labelFail
			// 
			this.labelFail.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelFail.ForeColor = System.Drawing.Color.Blue;
			this.labelFail.Location = new System.Drawing.Point( 8, 52 );
			this.labelFail.Name = "labelFail";
			this.labelFail.Size = new System.Drawing.Size( 92, 16 );
			this.labelFail.TabIndex = 2;
			this.labelFail.Text = "Failed:";
			// 
			// labelPass
			// 
			this.labelPass.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelPass.ForeColor = System.Drawing.Color.Blue;
			this.labelPass.Location = new System.Drawing.Point( 8, 36 );
			this.labelPass.Name = "labelPass";
			this.labelPass.Size = new System.Drawing.Size( 92, 16 );
			this.labelPass.TabIndex = 1;
			this.labelPass.Text = "Passed:";
			// 
			// labelExe
			// 
			this.labelExe.Font = new System.Drawing.Font( "Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)) );
			this.labelExe.ForeColor = System.Drawing.Color.Blue;
			this.labelExe.Location = new System.Drawing.Point( 8, 20 );
			this.labelExe.Name = "labelExe";
			this.labelExe.Size = new System.Drawing.Size( 92, 16 );
			this.labelExe.TabIndex = 0;
			this.labelExe.Text = "Executed Tests:";
			// 
			// groupBox2
			// 
			this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.groupBox2.Controls.Add( this.labelClass );
			this.groupBox2.Controls.Add( this.labelMethod );
			this.groupBox2.Controls.Add( this.labelAssembly );
			this.groupBox2.Controls.Add( this.label3 );
			this.groupBox2.Controls.Add( this.label2 );
			this.groupBox2.Controls.Add( this.Label1 );
			this.groupBox2.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.groupBox2.Location = new System.Drawing.Point( 14, 88 );
			this.groupBox2.Name = "groupBox2";
			this.groupBox2.Size = new System.Drawing.Size( 500, 76 );
			this.groupBox2.TabIndex = 4;
			this.groupBox2.TabStop = false;
			this.groupBox2.Text = "Current Test";
			// 
			// labelClass
			// 
			this.labelClass.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.labelClass.Location = new System.Drawing.Point( 104, 36 );
			this.labelClass.Name = "labelClass";
			this.labelClass.Size = new System.Drawing.Size( 382, 16 );
			this.labelClass.TabIndex = 5;
			// 
			// labelMethod
			// 
			this.labelMethod.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.labelMethod.Location = new System.Drawing.Point( 104, 52 );
			this.labelMethod.Name = "labelMethod";
			this.labelMethod.Size = new System.Drawing.Size( 382, 16 );
			this.labelMethod.TabIndex = 4;
			// 
			// labelAssembly
			// 
			this.labelAssembly.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.labelAssembly.Cursor = System.Windows.Forms.Cursors.AppStarting;
			this.labelAssembly.Location = new System.Drawing.Point( 104, 20 );
			this.labelAssembly.Name = "labelAssembly";
			this.labelAssembly.Size = new System.Drawing.Size( 382, 16 );
			this.labelAssembly.TabIndex = 3;
			// 
			// label3
			// 
			this.label3.Location = new System.Drawing.Point( 8, 52 );
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size( 92, 16 );
			this.label3.TabIndex = 2;
			this.label3.Text = "Method:";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point( 8, 36 );
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size( 92, 16 );
			this.label2.TabIndex = 1;
			this.label2.Text = "Class:";
			// 
			// Label1
			// 
			this.Label1.Location = new System.Drawing.Point( 8, 20 );
			this.Label1.Name = "Label1";
			this.Label1.Size = new System.Drawing.Size( 92, 16 );
			this.Label1.TabIndex = 0;
			this.Label1.Text = "Assembly:";
			// 
			// groupBox3
			// 
			this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.groupBox3.Controls.Add( this.labelEngineStatus );
			this.groupBox3.Controls.Add( this.labelEngineName );
			this.groupBox3.Controls.Add( this.label5 );
			this.groupBox3.Controls.Add( this.label4 );
			this.groupBox3.FlatStyle = System.Windows.Forms.FlatStyle.System;
			this.groupBox3.Location = new System.Drawing.Point( 16, 168 );
			this.groupBox3.Name = "groupBox3";
			this.groupBox3.Size = new System.Drawing.Size( 496, 64 );
			this.groupBox3.TabIndex = 5;
			this.groupBox3.TabStop = false;
			this.groupBox3.Text = "Test Execution Engine";
			// 
			// labelEngineStatus
			// 
			this.labelEngineStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.labelEngineStatus.Location = new System.Drawing.Point( 104, 40 );
			this.labelEngineStatus.Name = "labelEngineStatus";
			this.labelEngineStatus.Size = new System.Drawing.Size( 382, 16 );
			this.labelEngineStatus.TabIndex = 3;
			// 
			// labelEngineName
			// 
			this.labelEngineName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
						| System.Windows.Forms.AnchorStyles.Right)));
			this.labelEngineName.Location = new System.Drawing.Point( 104, 20 );
			this.labelEngineName.Name = "labelEngineName";
			this.labelEngineName.Size = new System.Drawing.Size( 382, 16 );
			this.labelEngineName.TabIndex = 2;
			// 
			// label5
			// 
			this.label5.Location = new System.Drawing.Point( 8, 40 );
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size( 52, 16 );
			this.label5.TabIndex = 1;
			this.label5.Text = "Status:";
			// 
			// label4
			// 
			this.label4.Location = new System.Drawing.Point( 8, 20 );
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size( 52, 16 );
			this.label4.TabIndex = 0;
			this.label4.Text = "Name:";
			// 
			// timerFormUiUpdate
			// 
			this.timerFormUiUpdate.Interval = 100;
			this.timerFormUiUpdate.Tick += new System.EventHandler( this.timerFormUiUpdate_Tick );
			// 
			// RunningTestsForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size( 5, 13 );
			this.ClientSize = new System.Drawing.Size( 528, 300 );
			this.Controls.Add( this.groupBox3 );
			this.Controls.Add( this.groupBox2 );
			this.Controls.Add( this.groupBox1 );
			this.Controls.Add( this.buttonCancel );
			this.Controls.Add( this.progressBarTest );
			this.Cursor = System.Windows.Forms.Cursors.AppStarting;
			this.Icon = ((System.Drawing.Icon)(resources.GetObject( "$this.Icon" )));
			this.KeyPreview = true;
			this.MaximizeBox = false;
			this.MaximumSize = new System.Drawing.Size( 1600, 336 );
			this.MinimumSize = new System.Drawing.Size( 350, 336 );
			this.Name = "RunningTestsForm";
			this.ShowInTaskbar = false;
			this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "HarnessIt is running tests. Please wait ...";
			this.Load += new System.EventHandler( this.RunningTestsForm_Load );
			this.Closing += new System.ComponentModel.CancelEventHandler( this.OnClosing );
			this.Resize += new System.EventHandler( this.RunningTestsForm_Resize );
			this.KeyDown += new System.Windows.Forms.KeyEventHandler( this.OnKeyDown );
			this.groupBox1.ResumeLayout( false );
			this.groupBox2.ResumeLayout( false );
			this.groupBox3.ResumeLayout( false );
			this.ResumeLayout( false );

		}

		#endregion

		#region Windows Form Event Handlers

		private void RunningTestsForm_Resize(object sender, EventArgs e)
		{
			try
			{
				buttonCancel.Left = (int)(Width/2.0f - buttonCancel.Width/2.0f);
				SetActiveText( false );
			}
			catch ( Exception ex )
			{
				Debug.WriteLine( "Resize Warning: " + ex.Message );
			}
		}

		private void RunningTestsForm_Load(object sender, EventArgs e)
		{
			RunningTestsFormPerstence ps = new RunningTestsFormPerstence( this );
			ps.InitializeWindow();

			RunningTestsForm_Resize( sender, e );
			this.progressBarTest.Focus();

			if ( SystemInformation.UserInteractive )
			{
				timerBackgroundUiAction.Start();
				timerFormUiUpdate.Start();
			}
		}

		private void buttonCancel_Click(object sender, EventArgs e)
		{
			timerFormUiUpdate.Enabled = false;
			timerBackgroundUiAction.Enabled = false;
			buttonCancel.Enabled = false;
			cancelled = true;
			this.Close();
		}

		private void timerFormUiUpdate_Tick(object sender, EventArgs e)
		{
			UpdateForm();
		}

		private void OnTimer1Tick(object sender, EventArgs e)
		{
			Stopwatch sw = new Stopwatch();
			sw.Start();
			while ( this.uiActionQueue.Count > 0 && sw.ElapsedMilliseconds < timerBackgroundUiAction.Interval/2.0 )
			{
				SendOrPostCallback callback;
				lock ( this.uiActionQueue )
				{
					callback = this.uiActionQueue.Dequeue();
				}
				callback( null );
			}

			if ( !once )
			{
				once = true;

				utThread = new Thread( RunTests );

				start = DateTime.Now;
				utThread.Name = "HarnessIt Test Execution Thread";
				utThread.IsBackground = true;
				utThread.Start();

				while ( !utThread.IsAlive )
				{
					Thread.Sleep( 5 );
				}
			}
			else
			{
				if ( utThread.IsAlive )
				{
					return;
				}

				end = DateTime.Now;
				this.DialogResult = DialogResult.OK;
				this.Close();
			}
		}

		internal void RunTestsInternal()
		{
			if ( !SystemInformation.UserInteractive )
			{
				start = DateTime.Now;
				RunTests();
				end = DateTime.Now;
				this.Close();
			}
		}

		private void OnKeyDown(object sender, KeyEventArgs e)
		{
			if ( e.KeyCode == Keys.Escape )
			{
				cancelled = true;
			}
		}

		private void OnClosing(object sender, CancelEventArgs e)
		{
			if ( this.DialogResult == DialogResult.Cancel )
			{
				this.DialogResult = DialogResult.None;
			}

			RunningTestsFormPerstence ps = new RunningTestsFormPerstence( this );
			ps.SaveWindow();
		}

		#endregion

	}
}